// 2025-4-3 chugehehe
#include "InetAddress.h"
#include "Endian.h"
#include "Logger.h"
#include "StringPiece.h"
#include "SocketsOps.h"

#include <netdb.h>
#include <cassert>
#include <cstdint>
#include <netinet/in.h>
#include <netdb.h>
#include <string.h>
#include <iostream>
#include <sys/socket.h>

//     /* Structure describing an Internet socket address.  */
//     struct sockaddr_in {
//         sa_family_t    sin_family; /* address family: AF_INET */
//         uint16_t       sin_port;   /* port in network byte order */
//         struct in_addr sin_addr;   /* internet address */
//     };

//     /* Internet address. */
//     typedef uint32_t in_addr_t;
//     struct in_addr {
//         in_addr_t       s_addr;     /* address in network byte order */
//     };

//     struct sockaddr_in6 {
//         sa_family_t     sin6_family;   /* address family: AF_INET6 */
//         uint16_t        sin6_port;     /* port in network byte order */
//         uint32_t        sin6_flowinfo; /* IPv6 flow information */
//         struct in6_addr sin6_addr;     /* IPv6 address */
//         uint32_t        sin6_scope_id; /* IPv6 scope-id */
//     };

// 特殊的 IPv4 地址
static constexpr in_addr_t kInaddrAny = INADDR_ANY; // 0.0.0.0
static constexpr in_addr_t kInaddrLoopback = INADDR_LOOPBACK; // 127.0.0.1

InetAddress::InetAddress(uint16_t port, bool loopbackOnly, bool ipv6)
{
    if(ipv6)
    {
        memset(&_addr6, 0, sizeof(_addr6));
        _addr6.sin6_family = AF_INET6;
        in6_addr ip = loopbackOnly ? in6addr_loopback : in6addr_any;
        _addr6.sin6_addr = ip;
        _addr6.sin6_port = sockets::hostToNetwork16(port);
    }
    else
    {
        memset(&_addr, 0, sizeof(_addr));
        _addr.sin_family = AF_INET;
        in_addr_t ip = loopbackOnly ? kInaddrLoopback : kInaddrAny;
        _addr.sin_addr.s_addr = sockets::hostToNetwork32(ip);
        _addr.sin_port = sockets::hostToNetwork16(port);
    }
}

InetAddress::InetAddress(StringArg ip, uint16_t port, bool ipv6)
{
    if(ipv6 || strchr(ip.c_str(), ':'))
    {
        memset(&_addr6, 0, sizeof(_addr6));
        sockets::fromIpPort(ip.c_str(), port, &_addr6);
    }
    else
    {
        memset(&_addr, 0, sizeof(_addr));
        sockets::fromIpPort(ip.c_str(), port, &_addr);
    }
}

string InetAddress::toIpPort() const
{
    char buf[64] = "";
    sockets::toIpPort(buf, sizeof buf, getSockAddr());
    return buf;
}

string InetAddress::toIp() const
{
    char buf[64] = "";
    sockets::toIp(buf, sizeof buf, getSockAddr());
    return buf;
}

uint32_t InetAddress::ipv4NetEndian() const
{
    assert(family() == AF_INET);
    return _addr.sin_addr.s_addr;
}

uint16_t InetAddress::port() const
{
    return sockets::networkToHost16(portNetEndian());
}

// gethostbyname非线程安全
// gethostbyname_r线程安全但需要提供线程安全的缓冲区
// 所以考虑线程局部存储
thread_local char t_resolveBuffer[64 * 1024];
bool InetAddress::resolve(StringArg hostname, InetAddress* result)
{
    assert(result != NULL);
    struct hostent hent;
    struct hostent* he = NULL;
    int herrno = 0; // 错误码
    int ret = gethostbyname_r(hostname.c_str(), &hent, t_resolveBuffer, sizeof t_resolveBuffer, &he, &herrno);
    if(ret == 0 || he != NULL)
    { // 仅支持ipv4 长度为4B
        assert(he->h_addrtype == AF_INET && he->h_length == sizeof(uint32_t));
        //从 he->h_addr 复制二进制形式的 IPv4 地址到目标的sin_addr
        result->_addr.sin_addr = *reinterpret_cast<struct in_addr*>(he->h_addr);
        return true;
    }
    else
    {
        if(ret) Logger::Error("InetAddress::resolve");
        return false;
    }
}

void InetAddress::setScopeId(uint32_t scope_id)
{
    if(family() == AF_INET6) _addr6.sin6_scope_id = scope_id;
}
